const promiseStatus = Symbol("PromiseStatus");
const promiseResult = Symbol("PromiseResult");

//声明 『构造函数』
function Promise(executor){


	const self = this ;
	// 添加属性
	// self.promiseStatus = 'pending';
	// self.promiseResult = undefined;
	// 
	self[promiseStatus] = 'pending'
	self[promiseResult] = []

	// 通过callbacks数组可以保存多个回调
	self.callbacks = []

	function resolve(...value) {
		// promise的状态只能 从pending改变为rejected/fulfilled状态，只能改变一次
		if(self[promiseStatus] !== 'pending') return ;
		self[promiseStatus] = 'fulfilled'; // resolved
		self[promiseResult] = value

		// 依次执行每个回调
		self.callbacks.forEach(item => {
			item.onResolved(self[promiseResult])
		})
	}

	function reject(...reason) {
		if(self[promiseStatus] !== 'pending') return ;
		self[promiseStatus] = 'rejected';
		self[promiseResult] = reason

		self.callbacks.forEach(item => {
			item.onRejected(self[promiseResult])
		})
	}

	try {
		executor(resolve, reject);
	}catch(err) {
		reject(err)
	}
}

// 原型对象上 添加 then方法
Promise.prototype.then = function(onResolved, onRejected) {
	const self = this

	if(typeof onResolved !== 'function') {
		onResolved = value => value
	}
	if(typeof onRejected !== 'function') {
		onRejected = reason => {
			throw reason
		}
	}

	return new Promise((resolve, reject) => {
		function callback(onTypeFn) {
			try{
				let ret = onTypeFn(...self[promiseResult])
				if(ret instanceof Promise) {
					ret.then(v => resolve(v), r => reject(r))
				} else {
					resolve(ret)
				}
			} catch(err) {
				reject(err)
			}
		}

		// resolve/reject改变promise的状态后，
		// 会执行 then方法中的 onResolved/onRejected 回调
		if(self[promiseStatus] === 'fulfilled') {
			setTimeout(() => {
				callback(onResolved)
			})
		}

		if(self[promiseStatus] === 'rejected') {
			setTimeout(() => {
				callback(onRejected)
			})
		}

		// pending状态是，需要保存回调函数，等到promise状态改变后进行回调
		if(self[promiseStatus] === 'pending') {
			// 返回值是在Promise构造函数遍历callbacks时才能获取到，
			// 嵌套一层函数, 而不是直接将onResolved/onRejected 交由Promise构造函数执行
			self.callbacks.push({
				onResolved: function (data) {
					setTimeout(() => {
						console.log('data', data === self[promiseResult], self[promiseResult], data)
						callback(onResolved)
					})

				},
				onRejected: function (reason) {
					setTimeout(() => {
						console.warn('reason', reason === self[promiseResult], self[promiseResult], reason)
						callback(onRejected)
					})
				}
			})
		}
	});

};


Promise.prototype.catch = function(onRejected) {
	return this.then(undefined, onRejected)
};



// ++++++++++++++++  构造函数对象上的方法， 静态方法, 返回promise对象 ++++++++++++++++
// 如果传入的参数为 非Promise类型的对象, 则返回的结果为成功promise对象
// 如果传入的参数为 Promise 对象, 则参数的结果决定了 resolve 的结果
Promise.resolve = function(value) {
	return new Promise((resolve, reject) => {
		if(value instanceof Promise) {
			value.then(v => resolve(v), r => reject(r))
		} else {
			resolve(value)
		}
	})
}


// 始终返回失败的promise
Promise.reject = function(reason) {
	return new Promise((resolve, reject) => {
		reject(reason)
	})
}


// 所有请求都成功，才会返回成功的promise
Promise.all = function(list) {
	var results = new Array()
	return new Promise((resolve, reject) => {
		var cnt = 0;
		list.forEach((promise, index) => {
			promise.then(value => {
				results[index] = value
				if(++cnt === list.length) {
					resolve(results)
				}
			}, reason => {
				reject(reason)
			})
			
		})
	})
}


// 只要有一个成功该返回的promise 就算成功
Promise.one = function(list) {
	var results = []
	var faileds = []
	return new Promise((resolve, reject) => {
		var failedCnt = 0;
		list.forEach((promise, index) => {
			promise.then(value => {
				results.push(value) 
			}, reason => {
				faileds[index] = reason
				if(++failedCnt === list.length) {
					reject(faileds)
				}
			})
		})
		resolve(results)
	})
}

// race 赛跑， 返回最先改变状态的promise, 可能成功也可能失败
Promise.race = function(list) {
	return new Promise((resolve, reject) => {
		list.forEach(promise => {
			promise.then(value => {
				 //修改返回对象的状态为 『成功』
				resolve(value)
			}, reason => {
				// 修改返回对象的状态为 『失败』
				reject(reason)
			})
		})
	})
}

